package com.jeesite.modules.dataScreen.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.ListMultimap;
import com.jeesite.modules.dataScreen.dao.IndustryIndexDao;
import com.jeesite.modules.dataScreen.spi.IndustryCollection;
import com.jeesite.modules.dataScreen.web.dto.IndustryIndexParam;
import com.jeesite.modules.dataScreen.web.vo.IndustryIndexFun;
import com.jeesite.modules.dataScreen.web.vo.IndustryIndexVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.stream.Collectors;

@Service
public class IndustryIndexService {

    private static final Map<String, IndustryCollection> INDUSTRY_COLLECTION_MAP = new ConcurrentHashMap<>();

    private final IndustryIndexDao industryIndexDao;

    @Autowired
    public IndustryIndexService(IndustryIndexDao industryIndexDao) {
        this.industryIndexDao = industryIndexDao;
    }


    public List<IndustryIndexVo> findAll(String... plates) {
        return industryIndexDao.findAll(plates);
    }

    public Map<String, IndustryIndexVo> findAllByIndicatorName(String... indicatorNames) {
        return industryIndexDao.findAllByIndicatorName(indicatorNames);
    }

    /**
     * 非实时数据
     *
     * @param industryNames 指标名称
     * @return 数据列表
     */
    public Map<String, IndustryIndexVo> getUnRealtime(String... industryNames) {
        return getUnRealtimeByParams(null, null, null, null, industryNames);
    }

    public Map<String, IndustryIndexVo> getUnRealtime(String[]... industryNames) {
        return getUnRealtimeByParams(null, null, null, null, ArrayUtil.addAll(industryNames));
    }

    /**
     * 非实时数据
     *
     * @param industryNames 指标名称
     * @return 数据列表
     */
    public Map<String, IndustryIndexVo> getUnRealtimeByParams(String plate, String runway, String subRunway, String liabilityUnit, String... industryNames) {
//        if (industryNames.length == 0) {
//            return Collections.emptyMap();
//        }
        List<String> indicatorNames = CollUtil.toList(industryNames);
        IndustryIndexParam indexParam = IndustryIndexParam.builder().plate(plate).runway(runway).subRunway(subRunway).liabilityUnit(liabilityUnit).indicatorNames(indicatorNames).build();
        return industryIndexDao.findUnRealtimeAllBy(indexParam);
    }

    /**
     * 实时数据
     *
     * @param industryNames 指标名称
     * @return 数据列表
     */
    public Map<String, IndustryIndexVo> getRealtime(String... industryNames) {
        Map<String, IndustryIndexVo> indexVoMap = getRealtimeByParams(null, null, null, null, industryNames);

        return indexVoMap;
    }

    public Map<String, IndustryIndexVo> getRealtime(String[]... industryNames) {
        return getRealtimeByParams(null, null, null, null, ArrayUtil.addAll(industryNames));
    }

    public void assembleColorAndTitle(Collection<IndustryIndexVo> indexVos) {
        for (IndustryIndexVo indexVo : indexVos) {
            String[] strings = IndustryIndexVo.titleAndColor(indexVo);
            if (strings != null) {
                indexVo.setColor(strings[1]);
                indexVo.setWarningTitle(strings[0]);
            }
        }
    }

    /**
     * 实时数据
     *
     * @param industryNames 指标名称
     * @return 数据列表
     */
    public Map<String, IndustryIndexVo> getRealtimeByParams(String plate, String runway, String subRunway, String liabilityUnit, String... industryNames) {
//        if (industryNames.length == 0) {
//            return Collections.emptyMap();
//        }
        List<String> indicatorNames = CollUtil.toList(industryNames);
        IndustryIndexParam indexParam = IndustryIndexParam.builder().plate(plate).runway(runway).subRunway(subRunway).liabilityUnit(liabilityUnit).indicatorNames(indicatorNames).build();
        return industryIndexDao.findRealtimeAllBy(indexParam);
    }

    public <T> void assembly(T result, boolean real, List<IndustryIndexFun<T>> funs, Consumer<IndustryIndexVo> consumer) {
        if (funs.isEmpty()) {
            return;
        }
        String[] array = funs.stream().map(IndustryIndexFun::getName).collect(Collectors.toList()).toArray(new String[]{});
        Map<String, IndustryIndexVo> indexVoMap = real ? getRealtime(array) : getUnRealtime(array);

        if (consumer != null) {
            indexVoMap.values().forEach(consumer);
        }
        for (IndustryIndexFun<T> fun : funs) {
            fun.apply(result, indexVoMap);
        }
    }

    public <T> void assembly(T result, boolean real, List<IndustryIndexFun<T>> funs) {
        assembly(result, real, funs, null);
    }

    public <T> void assembly(T result, Map<String, IndustryIndexVo> dataMap, List<IndustryIndexFun<T>> funs) {
        if (funs.isEmpty()) {
            return;
        }
        for (IndustryIndexFun<T> fun : funs) {
            fun.apply(result, dataMap);
        }
    }

    public List<IndustryIndexVo> getList(Map<String, IndustryIndexVo> dataMap, String... industryNames) {
        return getList(dataMap, null, industryNames);
    }

    public List<IndustryIndexVo> getList(Map<String, IndustryIndexVo> dataMap, Consumer<IndustryIndexVo> consumer, String... industryNames) {
        List<IndustryIndexVo> result = new ArrayList<>();
        for (String industryName : industryNames) {
//            IndustryIndexVo indexVo = dataMap.getOrDefault(industryName, IndustryIndexVo.NULL);
            IndustryIndexVo indexVo = dataMap.get(industryName);
            if (Objects.nonNull(consumer) && Objects.nonNull(indexVo)) {
                consumer.accept(indexVo);
            }
            if (indexVo == null) {
                indexVo = new IndustryIndexVo();
                indexVo.setIndicatorName(industryName);
            }
            result.add(indexVo);
        }
        return result;
    }

    public JSONObject standardLayout(String jsonPath) {
        IndustryCollection industryCollection = INDUSTRY_COLLECTION_MAP.computeIfAbsent(jsonPath, IndustryCollection::of);
        JSONObject result = new JSONObject();
        //查询指标数据
        Map<String, IndustryIndexVo> indexVoMap = findAllByIndicatorName(industryCollection.getSelectNames());
        //指标求和处理
        industryCollection.sumHandler(indexVoMap);
        ListMultimap<String, String> data = industryCollection.getData();
        for (String key : data.keys()) {
            List<IndustryIndexVo> indexVos = getList(indexVoMap, IndustryIndexVo.consumerColor(), industryCollection.getNameByKeys(key));
            //转化名称
            industryCollection.transferNames(indexVos);
            result.put(key, indexVos);
        }
        return result;
    }
}
